package com.dp.mallchat.common.chat.service.strategy;

import cn.hutool.core.bean.BeanUtil;
import com.dp.mallchat.common.chat.dao.MessageDao;
import com.dp.mallchat.common.chat.domain.entity.Message;
import com.dp.mallchat.common.chat.domain.enums.MessageTypeEnum;
import com.dp.mallchat.common.chat.domain.vo.req.SendMessageReq;
import com.dp.mallchat.common.chat.service.adapter.MessageAdapter;
import com.dp.mallchat.common.common.utils.AssertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.lang.reflect.ParameterizedType;

/**
 * @Author: dupeng
 * @CreateTime: 2024-06-28  15:18
 * @Description: 消息处理器
 */
@Component
public abstract class AbstractMsgHandler<Req> {

    @Autowired
    private MessageDao messageDao;
    private Class<Req> bodyClass;

    @PostConstruct
    private void init(){
        // 获取策略泛型，并赋值给bodyClass
        ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.bodyClass = (Class<Req>) genericSuperclass.getActualTypeArguments()[0];
//        bodyClass = (Class<Req>) ((java.lang.reflect.ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        MsgHandlerFactory.register(getMsgType().getType(), this);
    }



    /**
     * 初始化
     *获取消息类型（各策略）
     *检查消息  protected void checkMsg(Req body, Long roomId, Long uid)
     *检查并发送消息（统一）
     *获取请求对象
     *保存消息（策略）
     * 展示消息（策略）
     *被回复时——展示的消息(策略)
     * 会话列表——展示的消息（策略）
     */
    abstract MessageTypeEnum getMsgType();

    protected void checkMsg(Req body, Long roomId, Long uid){

    }

    /**
     * 保存消息统一入口，内部调用不同策略 消息检查和保存
     * @param req
     * @param uid
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long checkAndSaveMsg(SendMessageReq req, Long uid){
        // 获取请求对象
        Req reqBody = this.toBean(req.getBody());
        //校验请求对象
        AssertUtil.allCheckValidateThrow(reqBody);
        //子类扩展校验
        checkMsg(reqBody, req.getRoomId(), uid);
        //保存消息
        Message insert = MessageAdapter.buildSaveMessage(req.getRoomId(), uid, req.getMsgType());
        messageDao.save(insert);
        //子类扩展保存
        saveMsg(insert, reqBody);
        return insert.getId();
    }


    private Req toBean(Object body){
        if (bodyClass.isAssignableFrom(body.getClass())) {  //body.getClass()为LinkHashMap，入参如果为则为true
            return (Req) body;
        }
        return BeanUtil.toBean(body, bodyClass);
    }

    /**
     * 保存消息
     * @param message   消息
     * @param body  请求对象
     */
    protected abstract void saveMsg(Message message, Req body);

    /**
     * 展示消息
     */
    public abstract Object showMsg(Message msg);

    /**
     * 被回复时——展示的消息
     */
    public abstract Object showReplyMsg(Message msg);

    /**
     * 会话列表——展示的消息
     */
    public abstract String showContactMsg(Message msg);


}
